package org.example.jwtdemo.interceptors;

import com.auth0.jwt.exceptions.AlgorithmMismatchException;
import com.auth0.jwt.exceptions.SignatureVerificationException;
import com.auth0.jwt.exceptions.TokenExpiredException;
import com.auth0.jwt.interfaces.DecodedJWT;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.sun.jdi.VoidValue;
import jakarta.annotation.Resource;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import lombok.extern.slf4j.Slf4j;
import org.example.jwtdemo.entity.User;
import org.example.jwtdemo.mapper.UserMapper;
import org.example.jwtdemo.service.LoginService;
import org.example.jwtdemo.utils.Result;
import org.example.jwtdemo.utils.ThreadLocalUtils;
import org.example.jwtdemo.utils.jwtutils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.data.redis.core.ValueOperations;
import org.springframework.stereotype.Component;
import org.springframework.web.servlet.HandlerInterceptor;

import java.util.HashMap;
import java.util.Map;
@Component
public class JWTinterceptors implements HandlerInterceptor {//实现springMVC提供的拦截器接口

    @Autowired
    private StringRedisTemplate stringRedisTemplate;





    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        Map<String, Object> map = new HashMap<>();
        String token = request.getHeader("Authorization");//获取请求头中的token
        try {
            DecodedJWT verifyToken = jwtutils.verifyToken(token);
            //将token中的信息放入ThreadLocal中
            User user = new User();
            user.setId(Long.parseLong(verifyToken.getClaim("id").asString()));
            user.setUsername(verifyToken.getClaim("username").asString());
            user.setPassword(verifyToken.getClaim("password").asString());
            // 2. 从token中获取用户ID
            Long userId = Long.parseLong(verifyToken.getClaim("id").asString());
            //从redis中获取相同的token

           // ValueOperations<String, String> operations = stringRedisTemplate.opsForValue();
//            String redisToken = operations.get(token);
            // 3. 检查Redis中是否存在该用户的token
            ValueOperations<String, String> operations = stringRedisTemplate.opsForValue();
            String redisToken = operations.get(String.valueOf(userId));

            if (redisToken == null) {
                //http响应状态码为401
                response.setStatus(401);
                throw new Exception("token无效");
            }

            //希望在controller中 直接获取用户信息
            ThreadLocalUtils.set(user);//将token中的信息放入ThreadLocal中
            return true;//放行
        } catch (SignatureVerificationException e) {//签名异常
            e.printStackTrace();
            map.put("msg", "签名异常");
        }catch (TokenExpiredException e) {//token过期
            e.printStackTrace();
            map.put("msg", "token过期");
        }catch (AlgorithmMismatchException e) {//算法不匹配
            e.printStackTrace();
            map.put("msg", "token算法不匹配");
        }catch (Exception e) {
            e.printStackTrace();
            map.put("msg", "token无效");
        }
        map.put("code", "401");
        //将map转换为json字符串 jackson
        String json = new ObjectMapper().writeValueAsString(map);
        response.setContentType("application/json;charset=utf-8");//设置响应体格式为json
        response.getWriter().println(json);//响应给前端
        return false;
    }


    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
        //如果不删除 ThreadLocal中的用户信息，那么用户信息会一直存在,存在内存泄漏的风险
        ThreadLocalUtils.remove();//移除ThreadLocal中的用户信息
    }
}
